'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }

var crypto = _interopDefault(require('crypto'));

function createCommonjsModule(fn, module) {
	return module = { exports: {} }, fn(module, module.exports), module.exports;
}

var jwt_1 = createCommonjsModule(function (module) {
/*
 * jwt-simple
 *
 * JSON Web Token encode and decode module for node.js
 *
 * Copyright(c) 2011 Kazuhito Hokamura
 * MIT Licensed
 */

/**
 * module dependencies
 */



/**
 * support algorithm mapping
 */
var algorithmMap = {
  HS256: 'sha256',
  HS384: 'sha384',
  HS512: 'sha512',
  RS256: 'RSA-SHA256'
};

/**
 * Map algorithm to hmac or sign type, to determine which crypto function to use
 */
var typeMap = {
  HS256: 'hmac',
  HS384: 'hmac',
  HS512: 'hmac',
  RS256: 'sign'
};


/**
 * expose object
 */
var jwt = module.exports;


/**
 * version
 */
jwt.version = '0.5.6';

/**
 * Decode jwt
 *
 * @param {Object} token
 * @param {String} key
 * @param {Boolean} [noVerify]
 * @param {String} [algorithm]
 * @return {Object} payload
 * @api public
 */
jwt.decode = function jwt_decode(token, key, noVerify, algorithm) {
  // check token
  if (!token) {
    throw new Error('No token supplied');
  }
  // check segments
  var segments = token.split('.');
  if (segments.length !== 3) {
    throw new Error('Not enough or too many segments');
  }

  // All segment should be base64
  var headerSeg = segments[0];
  var payloadSeg = segments[1];
  var signatureSeg = segments[2];

  // base64 decode and parse JSON
  var header = JSON.parse(base64urlDecode(headerSeg));
  var payload = JSON.parse(base64urlDecode(payloadSeg));

  if (!noVerify) {
    if (!algorithm && /BEGIN( RSA)? PUBLIC KEY/.test(key.toString())) {
      algorithm = 'RS256';
    }

    var signingMethod = algorithmMap[algorithm || header.alg];
    var signingType = typeMap[algorithm || header.alg];
    if (!signingMethod || !signingType) {
      throw new Error('Algorithm not supported');
    }

    // verify signature. `sign` will return base64 string.
    var signingInput = [headerSeg, payloadSeg].join('.');
    if (!verify(signingInput, key, signingMethod, signingType, signatureSeg)) {
      throw new Error('Signature verification failed');
    }

    // Support for nbf and exp claims.
    // According to the RFC, they should be in seconds.
    if (payload.nbf && Date.now() < payload.nbf*1000) {
      throw new Error('Token not yet active');
    }

    if (payload.exp && Date.now() > payload.exp*1000) {
      throw new Error('Token expired');
    }
  }

  return payload;
};


/**
 * Encode jwt
 *
 * @param {Object} payload
 * @param {String} key
 * @param {String} algorithm
 * @param {Object} options
 * @return {String} token
 * @api public
 */
jwt.encode = function jwt_encode(payload, key, algorithm, options) {
  // Check key
  if (!key) {
    throw new Error('Require key');
  }

  // Check algorithm, default is HS256
  if (!algorithm) {
    algorithm = 'HS256';
  }

  var signingMethod = algorithmMap[algorithm];
  var signingType = typeMap[algorithm];
  if (!signingMethod || !signingType) {
    throw new Error('Algorithm not supported');
  }

  // header, typ is fixed value.
  var header = { typ: 'JWT', alg: algorithm };
  if (options && options.header) {
    assignProperties(header, options.header);
  }

  // create segments, all segments should be base64 string
  var segments = [];
  segments.push(base64urlEncode(JSON.stringify(header)));
  segments.push(base64urlEncode(JSON.stringify(payload)));
  segments.push(sign(segments.join('.'), key, signingMethod, signingType));

  return segments.join('.');
};

/**
 * private util functions
 */

function assignProperties(dest, source) {
  for (var attr in source) {
    if (source.hasOwnProperty(attr)) {
      dest[attr] = source[attr];
    }
  }
}

function verify(input, key, method, type, signature) {
  if(type === "hmac") {
    return (signature === sign(input, key, method, type));
  }
  else if(type == "sign") {
    return crypto.createVerify(method)
                 .update(input)
                 .verify(key, base64urlUnescape(signature), 'base64');
  }
  else {
    throw new Error('Algorithm type not recognized');
  }
}

function sign(input, key, method, type) {
  var base64str;
  if(type === "hmac") {
    base64str = crypto.createHmac(method, key).update(input).digest('base64');
  }
  else if(type == "sign") {
    base64str = crypto.createSign(method).update(input).sign(key, 'base64');
  }
  else {
    throw new Error('Algorithm type not recognized');
  }

  return base64urlEscape(base64str);
}

function base64urlDecode(str) {
  return Buffer.from(base64urlUnescape(str), 'base64').toString();
}

function base64urlUnescape(str) {
  str += new Array(5 - str.length % 4).join('=');
  return str.replace(/\-/g, '+').replace(/_/g, '/');
}

function base64urlEncode(str) {
  return base64urlEscape(Buffer.from(str).toString('base64'));
}

function base64urlEscape(str) {
  return str.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
}
});

const groupDepth = 3;
const groupMaxNumber = 7; // 一个账号下最多的团体数

const db = uniCloud.database();
const collection1 = db.collection('ha_report_list');
const collection2 = db.collection('ha_report_record');
const collection3 = db.collection('ha_group_person');

async function checkReportRecord(report_id,gp_id) {
	let res1 = await collection1
		.doc(report_id)
		.get();

	if (res1.data && res1.affectedDocs === 1) ; else {
		return false;
	}

	let res2 = await collection2
		.where({
			report_id,
			gp_id
		})
		.orderBy("create_time", "desc")
		.limit(1)
		.get();

	if (res2.data && res2.affectedDocs >= 1) {
		if (res2.data[0].allow_modify === 1) {
			return true;
		}

		// 检查间隔时间
		if (res1.data[0].interval_hour > 0) {
			if (Date.now() >= (res2.data[0].create_time + 3600000 * res1.data[0].interval_hour)) { // 一小时=3600000
				return true;
			}
		}

		return false;
	}

	return true;
}

async function getOneRecord(record_id) {
	let res2 = await collection2
		.doc(record_id)
		.get();

	if (res2.data && res2.affectedDocs === 1) ; else {
		return false;
	}

	if (res2.data[0].hasOwnProperty('report_id') == false) {
		return false;
	}

	let res1 = await collection1
		.doc(res2.data[0].report_id)
		.get();

	if (res1.data && res1.affectedDocs === 1) ; else {
		return false;
	}

	return {
		schema: res1.data[0].content,
		model: res2.data[0].model
	}
}

async function getReportRecord1(report_id,condition = {}) {
	let res2 = await collection2
		.where(
			Object.assign({
				report_id
			},condition)
		)
		.orderBy("create_time", "asc")
		.get();

	if (res2.data && res2.affectedDocs >= 1) ; else {
		return false;
	}

	let recordList = [];
	for (var i = 0; i < res2.data.length; i++) {
		let res3 = await collection3
			.doc(
				res2.data[i].gp_id
			)
			.get();

		let person_name = "未知";
		let person_identity = "";
		if (res3.data.length) {
			person_name = res3.data[0].person_name;
			person_identity = res3.data[0].person_identity;
		}

		recordList.push(
			Object.assign({
				person_name,
				person_identity,
				create_time: res2.data[i].create_time
			},
			res2.data[i].model
			)
		);
	}

	return recordList;
}

async function getReportList(group_id) {
	let res = await collection1
		.where({
			group_id
		})
		.get();

	return res.data;
}

async function checkReportName(group_id,name) {
	let res = await collection1
		.where({
			group_id,
			name
		})
		.get();

	if (res.data && res.affectedDocs >= 1) {
		return false;
	} else {
		return true;
	}
}

async function getReportUndo(report_id,condition = {}) {
	let res1 = await collection1
		.doc(report_id)
		.get();

	if (res1.data && res1.affectedDocs === 1) ; else {
		return false;
	}

	let res3 = await collection3
		.where({
			group_id: res1.data[0].group_id
		})
		.get();

	let personUndo = [];
	for (var i = 0; i < res3.data.length; i++) {
		let res2 = await collection2
			.where(
				Object.assign({
					report_id,
					gp_id: res3.data[i]._id
				},condition)
			)
			.get();

		if (res2.data && res2.affectedDocs >= 1) ; else {
			personUndo.push({person_name: res3.data[i].person_name});
		}
	}

	return personUndo;
}

async function getReportRecord2(report_id,page,length) {
	const result = await collection2
		.where({
			report_id
		})
		.orderBy("create_time","desc")
		.skip(length * page)
		.limit(length)
		.get();

	const recordList = [];
	for (var i = 0; i < result.data.length; i++) {
		const {
			_id,
			gp_id,
			create_time,
			model
		} = result.data[i];

		let tmp = await collection3
			.doc(gp_id)
			.get();

		let person_name = "未知";
		if (tmp.data.length) {
			person_name = tmp.data[0].person_name;
		}

		recordList.push({
			_id,
			gp_id,
			person_name,
			create_time,
			model
		});
	}

	return recordList;
}

var reportFunc = {
	checkReportRecord,
	getOneRecord,
	getReportRecord1,
	getReportList,
	checkReportName,
	getReportUndo,
	getReportRecord2
};

const db$1 = uniCloud.database();
const collection = db$1.collection('ha_group_list');

async function getChildGroupID(group_id,depth) {
	if ( depth >= groupDepth ) {
		return [];
	}

	let result = [];
	depth += 1;

	let res = await collection
		.where({
			parent_id: group_id
		})
		.get();

	for ( let i = 0; i < res.data.length; i++ ) {
		result.push(res.data[i]._id);

		if ( res.data[i].hasOwnProperty('is_split') == false || res.data[i].is_split != true ) {
			result = result.concat(await getChildGroupID(res.data[i]._id,depth));
		}
	}

	return result;
}

async function getFirstChildGroup(group_id) {
	let res = await collection
		.where({
			parent_id: group_id
		})
		.get();

	return res.data;
}

async function updateGroupParent(group_id,parent_id) {
	await collection
		.doc(group_id)
		.update({
			parent_id
		});
}

async function deleteOneGroup(group_id) {

	await db$1.collection('ha_group_person')
		.where({
			group_id
		})
		.remove();

	// await db.collection('ha_group_notice')
	// 	.where({
	// 		group_id
	// 	})
	// 	.remove();

	await db$1.collection('ha_report_list')
		.where({
			group_id
		})
		.remove();

	// await db.collection('ha_report_summary')
	// 	.where({
	// 		group_id
	// 	})
	// 	.remove();

	await collection
		.doc(group_id)
		.remove();
}

async function checkGroupNumber(account_id) {
	let res = await collection
		.where({
			account_id
		})
		.get();

	if (res.data && res.affectedDocs >= groupMaxNumber) {
		return false
	}
	return true;
}

async function checkGroupDepth(account_id,group_id) {
	// 1. 自己的团体
	// 2. 下属团体
	// 3. 最远端下属团体

	let res;
	for ( let i = 0; i <= groupDepth; i++ ) {
		res = await collection
			.doc(group_id)
			.get();

		if (res.data && res.affectedDocs === 1) {
			if (res.data[0].account_id == account_id) {
				if (i == 0) {
					return 1;
				} else if (i < groupDepth) {
					return 2;
				} else {
					return 3;
				}
			}
			group_id = res.data[0].parent_id;
		} else {
			return 0;
		}
	}
	return 0;
}

async function updateGroupItem(group_id,group_info) {
	await collection
		.doc(group_id)
		.update(group_info);
}

async function checkGroupItem(group_id,group_cond) {
	let res = await collection
		.where(Object.assign(group_cond,{
			_id: group_id
		}))
		.limit(1)
		.get();

	return (res.data && res.affectedDocs >= 1) ? true : false;
}

var groupFunc = {
	getChildGroupID,
	getFirstChildGroup,
	updateGroupParent,
	deleteOneGroup,
	checkGroupNumber,
	checkGroupDepth,
	updateGroupItem,
	checkGroupItem
};

const db$2 = uniCloud.database();

async function Perform(event) {
	if (!event.name) {
		return {
			status: -4,
			msg: '请输入报备名称！'
		}
	}

	const collection = db$2.collection('ha_user_account');
	let user = await collection
		.doc(
			event.account_id
		)
		.get();
	
	if (user.data && user.affectedDocs === 1); else {
		return {
			status: -1,
			msg: "请重新登录！"
		}
	}

	const collection1 = db$2.collection('ha_group_list');
	let res1 = await collection1
		.doc(
			event.group_id
		)
		.get();
	
	if (res1.data && res1.affectedDocs === 1); else {
		return {
			status: -2,
			msg: "请先进入团体，再创建！"
		}
	}

	const collection2 = db$2.collection('ha_template_list');
	let res2 = await collection2
		.doc(
			event.tpl_id
		)
		.get();
	
	if (res2.data && res2.affectedDocs === 1); else {
		return {
			status: -3,
			msg: "抱歉，模板不存在！"
		}
	}

	let isPass = await reportFunc.checkReportName(event.group_id,event.name);

	if (isPass != true) {
		return {
			status: -4,
			msg: '请不要创建重名报备！'
		}
	}

	let data = {
		group_id: event.group_id,
		group2_id: event.group_id,
		name: event.name,
		is_active: event.is_active,
		check_member: event.check_member,
		interval_hour: event.interval_hour,
		tpl_id: event.tpl_id,
		tpl_name: res2.data[0].name,
		content: res2.data[0].content
	};

	const collection3 = db$2.collection('ha_report_list');
	let res3 = await collection3.add(data);

	// 创建下属团体的报备记录
	let childList = await groupFunc.getChildGroupID(event.group_id,0);

	for ( let i = 0; i < childList.length; i++ ) {
		data.group_id = childList[i];
		await db$2.collection('ha_report_list').add(data);
	}

	return {
		status: 0,
		report_id: res3.id,
		child: childList, // 调试查看子团体
		msg: "创建成功！"
	}
}

exports.main = Perform;
